package service

import (
	"CDSystem/v2/config"
	"CDSystem/v2/dao"
	"CDSystem/v2/model"
	"CDSystem/v2/utils"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

func InferToApi(ir model.InferRequest) (model.ClientResponse, error) {
	cRes := model.ClientResponse{}
	var err error
	defer func() {
		if err != nil {
			cRes.Err = err.Error()
		}
	}()
	//先查询数据库，若库中有推理结果则直接调库，否则向InferAPI发送POST请求，获取结果组装cRes，并将label存入mongodb数据库
	ImageMd5 := utils.Md5Crypt(ir.ImageA, ir.Task) + utils.Md5Crypt(ir.ImageB, ir.Task)
	label, image, err := dao.GetLabelAndImage(ImageMd5)
	if err != nil {
		log.Println("该图片未处理，调用推理接口")
		log.Println(err)
		//向推理API发送请求
		cResJson, err := json.Marshal(&ir)
		if err != nil {
			return cRes, err
		}
		rspBody, err := sendPost(cResJson, config.Cfg.System.InferApiUrl+"/api/infer")
		if err != nil {
			return cRes, err
		}
		var res model.InferResponse
		//log.Println(rspBody)
		if err = json.Unmarshal(rspBody, &res); err != nil {
			return cRes, err
		}
		if res.Code != 200 {
			err = errors.New(res.Err)
			return cRes, err
		}
		//将label存入数据库
		ProdInfo := model.ProdInfo{
			Image:     ImageMd5,
			Label:     res.Label,
			ImageData: ir.ImageA,
		}
		if err = dao.SaveProd(ProdInfo); err != nil {
			return cRes, err
		}
		cRes.Image = ImageMd5
		cRes.Code = res.Code
		cRes.Prod = res.Prod
		cRes.Time = res.Time
		return cRes, err
	} else {
		//调用后处理API
		log.Println("该图片已处理，直接调用后处理函数")
		pr := model.PostRequest{
			Task:     ir.Task,
			Label:    label,
			Image:    image,
			Postfunc: "default",
		}
		prJson, err := json.Marshal(&pr)
		if err != nil {
			return cRes, err
		}
		rspBody, err := sendPost(prJson, config.Cfg.System.InferApiUrl+"/api/postprocess")
		if err != nil {
			return cRes, err
		}
		var res model.PostResponse
		if err = json.Unmarshal(rspBody, &res); err != nil {
			return cRes, err
		}
		if res.Code != 200 {
			err = errors.New(res.Err)
			return cRes, err
		}
		cRes.Image = ImageMd5
		cRes.Code = res.Code
		cRes.Prod = res.Prod
		cRes.Time = res.Time
		return cRes, err
	}
}

func sendPost(requestParam []byte, url string) (rspBody []byte, err error) {
	log.Println("发送post请求。。。" + url)
	reqBody := strings.NewReader(string(requestParam))
	httpReq, err := http.NewRequest("POST", url, reqBody)
	if err != nil {
		return
	}
	httpReq.Header.Add("Content-Type", "application/json")
	httpRsp, err := http.DefaultClient.Do(httpReq)
	if err != nil {
		return
	}
	defer httpRsp.Body.Close()

	rspBody, err = ioutil.ReadAll(httpRsp.Body)
	if err != nil {
		return
	}

	return
}
